package com.hup.minicontroller.common.thread;

import com.hup.minicontroller.common.thread.component.EfficientExecutor;
import com.hup.minicontroller.common.thread.component.PrefixAbleThreadFactory;
import com.hup.minicontroller.common.thread.component.SimpleRejectedHandler;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池工具类
 * <pre>
 *     本类创建两类执行器: {@link EfficientExecutor}, {@link ThreadPoolExecutor}
 *     注释详见{@link EfficientExecutor}
 * </pre>
 *
 * @author hugan
 * @date 2020/4/30
 */
public class ThreadPoolUtil {

    /**
     * ui执行器
     * <pre>
     * 需求
     *  对任务同时执行要求不高,但要同时支持两个任务也不过分
     *  任务量:少,单线程满足最常见情况
     * 配置
     *  常驻线程:1
     *  最大线程:5
     *  最大任务数:5+20等待队列
     * </pre>
     *
     * @param threadNamePrefix 线程名前缀,一般以'-'结尾
     * @param executorDesc 执行器描述,如[窗口标题];用于 {@link RejectedExecutionException} 的消息描述
     */
    public static ThreadPoolExecutor uiExecutor(String threadNamePrefix, String executorDesc) {
        return new EfficientExecutor(
                1, 5,
                20,
                30, TimeUnit.SECONDS,
                threadNamePrefix,
                executorDesc);
    }

    /**
     * 固定线程的执行器
     * <pre>
     * 配置
     *  常驻线程:0
     *  最大线程:threadCount
     *  最大任务数:threadCount+0等待队列
     *  回收间隔:10秒
     * </pre>
     *
     * @param threadNamePrefix 线程名前缀,一般以'-'结尾
     * @param executorDesc 执行器描述,如[窗口标题];用于 {@link RejectedExecutionException} 的消息描述
     */
    public static ThreadPoolExecutor fixedThreadExecutor(String threadNamePrefix, int threadCount,
            String executorDesc) {
        return new ThreadPoolExecutor(
                0,
                threadCount,
                10, TimeUnit.SECONDS,
                new SynchronousQueue<>(),
                //实现修改线程名前缀
                new PrefixAbleThreadFactory(threadNamePrefix),
                //达到最大任务时抛出异常
                new SimpleRejectedHandler(executorDesc)
        );
    }

}
